package com.dd.cloud.user.service.phar.pharservice;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.dd.cloud.common.constants.OrderConstants;
import com.dd.cloud.common.constants.PharConstants;
import com.dd.cloud.common.constants.PresConstants;
import com.dd.cloud.common.enums.ZkExceptionEnum;
import com.dd.cloud.common.exception.ZekeException;
import com.dd.cloud.common.interceptor.UserInterceptor;
import com.dd.cloud.common.utils.JsonUtils;
import com.dd.cloud.common.utils.Md5Utils;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.user.DTO.CallbackPresStatusReq;
import com.dd.cloud.user.DTO.CancelPresReq;
import com.dd.cloud.user.DTO.CommonParamReq;
import com.dd.cloud.user.DTO.hst.*;
import com.dd.cloud.user.entity.doctor.PatientMedCard;
import com.dd.cloud.user.entity.order.OrderPay;
import com.dd.cloud.user.entity.phar.Pharmacy;
import com.dd.cloud.user.entity.phar.PharmacyDocking;
import com.dd.cloud.user.entity.pres.PresHstDetail;
import com.dd.cloud.user.entity.pres.PresHstPharRoam;
import com.dd.cloud.user.entity.pres.PresPrescription;
import com.dd.cloud.user.entity.pres.PresPretrialDrugs;
import com.dd.cloud.user.enums.ExceptionEnum;
import com.dd.cloud.user.req.pres.PresCreateHstReq;
import com.dd.cloud.user.req.pres.PresCreateReq;
import com.dd.cloud.user.req.pres.PresPatientAddrReq;
import com.dd.cloud.user.service.log.ILogErrorService;
import com.dd.cloud.user.service.order.IOrderPayService;
import com.dd.cloud.user.service.phar.IPharmacyDockingService;
import com.dd.cloud.user.service.phar.IPharmacyService;
import com.dd.cloud.user.service.pres.*;
import com.dd.cloud.user.vo.PharResponseVo;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @Description: // 和顺堂药房操作，
 * @ClassName: HjtPharService
 * @Author: czg
 * @Date: 2023/11/6 17:20
 * @Version: 1.0
 */
@Slf4j
@Service
public class HstPharService extends PharAbstractService {
    @Autowired
    private IPresHstDetailService presHstDetailService;
    @Autowired
    private IPresHstPharRoamService presHstPharRoamService;
    @Autowired
    private IOrderPayService orderPayService;
    @Autowired
    private ILogErrorService logErrorService;
    @Autowired
    private IPresPrescriptionService presPrescriptionService;
    @Autowired
    private IPharmacyService pharmacyService;
    @Autowired
    private IPresPretrialDrugsService presPretrialDrugsService;
    @Autowired
    private IPharmacyDockingService pharmacyDockingService;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private IDrugsModelService drugsModelService;

    /**
     * 添加药房的处方详情
     *
     * @param req
     * @param medCard
     */
    @Override
    public void addPresDetail(PresCreateReq req, PatientMedCard medCard) {
        LoginInfo loginInfo = UserInterceptor.getLoginUserInfo().get();
        PresHstDetail detail = new PresHstDetail();
        PresCreateHstReq hstReq = (PresCreateHstReq) req;

        detail.setTencode(req.getTencode());
        detail.setDoctorName(loginInfo.getName());
        detail.setPatientAge(medCard.getAge());
        detail.setPatientBod(medCard.getBirthDate());
        detail.setDecoctDesc("无");
        detail.setDescribeStr("无");
        detail.setRecvName(hstReq.getRecvName());
        detail.setRecvTel(hstReq.getRecvTel());
        detail.setProvinceName(hstReq.getProvinceName());
        detail.setCityName(hstReq.getCityName());
        detail.setAreaName(hstReq.getAreaName());
        detail.setAddress(hstReq.getAddress());
        detail.setMedicationMethod(hstReq.getMedicationMethod());
        boolean i = presHstDetailService.saveOrUpdate(detail);
        if (!i) {
            throw new ZekeException(ExceptionEnum.PRES_CREATE_ERROR, "处方信息保存失败");
        }
    }

    /**
     * @param pay: 支付回调调用, 订单参数
     * @return void
     * @author czg
     * @description 发送处方到和顺堂药房, 参考接口文档https://docs.qq.com/doc/DUFNsUkdOYWRIRGJX
     * @date 2023/11/6 14:19
     */
    @Override
    public boolean sendPresToPhar(OrderPay pay) {
        log.info("发送处方到和顺堂药房");
        boolean succ = false;
        if (StringUtils.isBlank(pay.getServerNo())) {
            //没有处方编码 数据异常, 退款
            orderPayService.refund(pay.getOrderNo(), 0);
            logErrorService.presBackLog("没有处方编码-数据异常, 退款", "处方发送到和顺堂药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        PresPrescription presPrescription = presPrescriptionService.getById(pay.getServerNo());
        if (presPrescription == null) {
            //处方为空, 数据异常
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("处方为空-数据异常", "处方发送到和顺堂药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        if (presPrescription.getStatus() == PresConstants.PresStatus.SENDPHARM) {
            //处方已发送到药房, 此为重复回调
            log.info("处方已发送到药房, 此为重复回调");
            return succ;
        }
        PresHstDetail hstDetail = presHstDetailService.getById(pay.getServerNo());
        if (hstDetail == null) {
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("获取发送给药房的详细数据失败", "处方发送到和顺堂药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        Pharmacy pharmacy = pharmacyService.getById(presPrescription.getPharmId());
        if (pharmacy == null) {
            //药房为空, 数据异常
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("药房为空-数据异常, 退款", "处方发送到和顺堂药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        QueryWrapper<PresPretrialDrugs> qw = new QueryWrapper<>();
        qw.lambda().eq(PresPretrialDrugs::getTencode, presPrescription.getTencode()).eq(PresPretrialDrugs::getStatus, PresConstants.PresDrugsStatus.NOMER);
        List<PresPretrialDrugs> drugsList = presPretrialDrugsService.list(qw);
        if (drugsList == null || drugsList.isEmpty()) {
            //没有处方药品, 数据异常, 退款
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("没有处方药品-数据异常", "处方发送到和顺堂药房异常", "tencode=" + pay.getServerNo());
            return succ;
        }
        QueryWrapper<PharmacyDocking> qd = new QueryWrapper<>();
        qd.lambda().eq(PharmacyDocking::getPharId, pharmacy.getId()).eq(PharmacyDocking::getStatus, PharConstants.DockingStatus.NOMER);
        PharmacyDocking pharmacyDocking = pharmacyDockingService.getOne(qd);
        if (pharmacyDocking == null) {
            //药房为空, 数据异常
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("药房对接信息为空-数据异常", "处方发送到和顺堂药房异常", "pharId=" + pharmacy.getId());
            return succ;
        }
        HstSendPresReqDTO hst = new HstSendPresReqDTO();
        hst.setChannel_id(pharmacyDocking.getMchId());
        hst.setInst_order_no(pay.getOrderNo());
        hst.setPatient_code(presPrescription.getMedId());
        hst.setPatient_name(presPrescription.getName());
        hst.setPatient_sex(presPrescription.getSex().equals("男") ? "1" : "2");
        hst.setPatient_mp(presPrescription.getPhoneNum());
        hst.setPatient_age(presPrescription.getAge());
        hst.setPatient_address(hstDetail.getProvinceName() + hstDetail.getCityName() + hstDetail.getAreaName() + hstDetail.getAddress());
        hst.setPatient_medical_history("无");
        hst.setPatient_allergy("无");
        hst.setPatient_bod(hstDetail.getPatientBod().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        hst.setDepartment(presPrescription.getDepartmentName());
        hst.setDoctor_code(String.valueOf(presPrescription.getDoctorId()));
        hst.setDoctor_name(hstDetail.getDoctorName());
        hst.setDiagnose(presPrescription.getDiseaseName());
        hst.setSymptom(presPrescription.getSymptomList());
        hst.setMedical_advice(presPrescription.getAdvice());
        hst.setDate(presPrescription.getCreateDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        HstSendPresDeliveryDTO deliveryDTO = new HstSendPresDeliveryDTO();
        deliveryDTO.setRecv_name(hstDetail.getRecvName());
        deliveryDTO.setRecv_tel(hstDetail.getRecvTel());
        deliveryDTO.setAddress(presPrescription.getAddress());
        deliveryDTO.setProvince_name(hstDetail.getProvinceName());
        deliveryDTO.setCity_name(hstDetail.getCityName());
        deliveryDTO.setArea_name(hstDetail.getAreaName());
        deliveryDTO.setAddress(hstDetail.getAddress());
        hst.setDelivery_info(deliveryDTO);
        HstSendPresDrugReqDTO sendDrugs = new HstSendPresDrugReqDTO();
        List<HstSendPresDrugReqDTO.PresDrugDTO> drugDTOS = new ArrayList<>();
        for (PresPretrialDrugs drugs : drugsList) {
            HstSendPresDrugReqDTO.PresDrugDTO drugDTO = new HstSendPresDrugReqDTO.PresDrugDTO();
            drugDTO.setDrug_code(drugs.getDrugnum());
            drugDTO.setName(drugs.getHerbName());
            drugDTO.setAction(drugs.getDecocting());
            drugDTO.setNum(drugs.getDrugallnum().intValue());
            drugDTO.setPrice(String.valueOf(drugs.getOriginalPrice() / 100));
            drugDTO.setUnit(drugs.getUnit());
            drugDTOS.add(drugDTO);
        }
        sendDrugs.setDrug_list(drugDTOS);
        sendDrugs.setPres_no(presPrescription.getTencode());
        sendDrugs.setMedication_method(hstDetail.getMedicationMethod());
        sendDrugs.setIs_decoct(presPrescription.getType());
        sendDrugs.setDecoct_desc(hstDetail.getDecoctDesc());
        sendDrugs.setDose(presPrescription.getAllDose());
        sendDrugs.setDescribe(hstDetail.getDescribeStr());
        List<HstSendPresDrugReqDTO> presList = new ArrayList<>();
        presList.add(sendDrugs);
        hst.setPair_list(presList);
        //参数转json 并对参数按字母排序
        Map pramMap = JSONObject.parseObject(JSONObject.toJSONString(hst), Feature.OrderedField);
        String serial = JSON.toJSONString(pramMap);
        String sign = Md5Utils.encryptionMD5(serial + pharmacyDocking.getSecretKey());
        String res;
        try {
//            Map<String, String> head = new HashMap<>();
//            head.put("Auth-Type", "MD5");
//            head.put("Sign", sign);
//            head.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE);
            HttpHeaders head = new HttpHeaders();
            head.add("Auth-Type", "MD5");
            head.add("Sign", sign.toUpperCase());
            head.setContentType(MediaType.APPLICATION_JSON_UTF8);
            HttpEntity<String> entity = new HttpEntity<>(JsonUtils.objectToStr(hst), head);
            log.info("和顺堂药房提交处方请求参数:{}", JSON.toJSONString(hst));
            res = restTemplate.postForObject(pharmacyDocking.getServicesUrl(), entity, String.class);
//            res = HttpRequestUtils.post(pharmacyDocking.getServicesUrl(), JSON.toJSONString(hst), head);
            log.info("和顺堂药房返回:{}", res);
        } catch (Exception e) {
            log.info(e.getMessage());
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("请求参数数据加密失败", "处方发送和顺堂药房异常", "bodyDTO=" + JSON.toJSONString(e.getMessage()));
            return succ;
        }
        HstResDTO<HstSendPresResDTO> resDTO;
        try {
            resDTO = JsonUtils.nativeRead(res, new TypeReference<HstResDTO<HstSendPresResDTO>>() {
            });
        } catch (Exception e) {
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("药房返回数据json解析失败", "处方发送到和顺堂药房异常", "res=" + res);
            return succ;
        }
        if (resDTO == null) {
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("药房返回数据空", "处方发送到和顺堂药房异常", "res=" + res);
            return succ;
        }
        if (!"SUCCESS".equals(resDTO.getReturn_msg()) || !"200".equals(resDTO.getResult_code())) {
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("药房返回状态码异常", "处方发送到和顺堂药房异常", "msg=" + resDTO.getReturn_msg() + "/" + resDTO.getResult_msg());
            return succ;
        }
        presPrescription.setStatus(PresConstants.PresStatus.SENDPHARM);
        presPrescription.setUpdateDate(LocalDateTime.now());
        boolean flag = presPrescriptionService.updateById(presPrescription);
        if (!flag) {
            presPrescription.setStatus(PresConstants.PresStatus.SENDPHARMERROR);
            presPrescriptionService.updateById(presPrescription);
            logErrorService.presBackLog("发送处方到药房成功, 处方更新失败", "处方发送到和顺堂药房异常", "jsonBody=" + presPrescription);
            return succ;
        }
        hstDetail.setOrderNo(resDTO.getResult_data().getOrder_no());
        presHstDetailService.updateById(hstDetail);
        succ = true;
        return succ;
    }

    /**
     * @param req:
     * @return void
     * @author czg
     * @description 和顺堂取消处方
     * @date 2023/11/7 9:45
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelPres(CancelPresReq req) {
        PresPrescription presPrescription = presPrescriptionService.getById(req.getTencode());
        if (presPrescription == null) {
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "查询处方失败");
        }
        Pharmacy pharmacy = pharmacyService.getById(presPrescription.getPharmId());
        if (pharmacy == null) {
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "查询药房失败");
        }
        QueryWrapper<PharmacyDocking> qd = new QueryWrapper<>();
        qd.lambda().eq(PharmacyDocking::getPharId, pharmacy.getId()).eq(PharmacyDocking::getStatus, PharConstants.DockingStatus.NOMER);
        PharmacyDocking pharmacyDocking = pharmacyDockingService.getOne(qd);
        if (pharmacyDocking == null) {
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "查询药房信息失败");
        }
        QueryWrapper<OrderPay> qw = new QueryWrapper<>();
        qw.lambda().eq(OrderPay::getServerNo, req.getTencode()).eq(OrderPay::getProduct, OrderConstants.Product.PRE).ne(OrderPay::getStatus, OrderConstants.Status.CANCEL).orderByDesc(OrderPay::getCreateDate).last("limit 1");
        OrderPay orderPay = orderPayService.getOne(qw);
        if (orderPay == null) {
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "查询订单信息失败");
        }
        HstCancelPresDTO cancelPresDTO = new HstCancelPresDTO();
        cancelPresDTO.setChannel_id(pharmacyDocking.getMchId());
        cancelPresDTO.setInst_order_no(orderPay.getOrderNo());
        Map pramMap = JSONObject.parseObject(JSONObject.toJSONString(cancelPresDTO), Feature.OrderedField);
        String serial = JSON.toJSONString(pramMap);
        String sign = Md5Utils.encryptionMD5(serial + pharmacyDocking.getSecretKey());
        String res;
        try {
            HttpHeaders head = new HttpHeaders();
            head.add("Auth-Type", "MD5");
            head.add("Sign", sign.toUpperCase());
            HttpEntity<String> entity = new HttpEntity<>(JsonUtils.objectToStr(cancelPresDTO), head);
            log.info("和顺堂药房取消处方请求参数:{}", JSON.toJSONString(entity));
            res = restTemplate.postForObject(pharmacyDocking.getCancelUrl(), entity, String.class);
            log.info("和顺堂药房取消处方返回:{}", res);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "调用药房取消处方接口异常");
        }
        HstResDTO resDTO;
        try {
            resDTO = JsonUtils.parse(res, HstResDTO.class);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "药房接口解析失败,请联系管理员");
        }
        if (!"SUCCESS".equals(resDTO.getReturn_msg()) || !"200".equals(resDTO.getResult_code())) {
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, resDTO.getResult_msg());
        }
        presPrescription.setStatus(PresConstants.PresStatus.CANCEL);
        boolean flag = presPrescriptionService.updateById(presPrescription);
        if (!flag) {
            logErrorService.presBackLog("取消处方和顺堂返回成功,数据修改失败", "取消处方", "tencode=" + presPrescription.getTencode());
            throw new ZekeException(ZkExceptionEnum.CANCEL_PRES_ERROR, "数据修改失败,请联系管理员");
        }
    }

    /**
     * @param req:
     * @return PharResponseVo
     * @author czg
     * @description 和顺堂处方状态回传
     * @date 2022/12/5 15:38
     */
    @Override
    public PharResponseVo presCallback(CallbackPresStatusReq req) {
        return null;
    }

    /**
     * @param req:
     * @return void
     * @author czg
     * @description 物流信息回调
     * @date 2022/12/6 10:24
     */
    @Override
    public HstResDTO<HstExpressResDTO> expressCallback(CommonParamReq req) {
        String sign = req.getRequest().getHeader("Sign");
        if (StringUtils.isBlank(sign)) {
            throw new ZekeException(400, "签名不能为空");
        }
        log.info("和顺堂物流回调");
        HstExpressReportReq hstReq = (HstExpressReportReq) req.toExpressPojo();
        QueryWrapper<Pharmacy> qp = new QueryWrapper<>();
        qp.lambda().eq(Pharmacy::getFlag, PharConstants.Flag.HST);
        Pharmacy pharmacy = pharmacyService.getOne(qp);
        if (pharmacy == null) {
            throw new ZekeException(400, "查询药房失败");
        }
        QueryWrapper<PharmacyDocking> qd = new QueryWrapper<>();
        qd.lambda().eq(PharmacyDocking::getPharId, pharmacy.getId()).eq(PharmacyDocking::getStatus, PharConstants.DockingStatus.NOMER);
        PharmacyDocking pharmacyDocking = pharmacyDockingService.getOne(qd);
        if (pharmacyDocking == null) {
            throw new ZekeException(400, "查询药房信息失败");
        }
        String serial = JSONObject.toJSONString(hstReq, SerializerFeature.MapSortField);
        log.info("serial:{}", serial);
        String signs = Md5Utils.encryptionMD5(serial + pharmacyDocking.getSecretKey());
        log.info("sign:{},signs:{}", sign, signs);
        if (!sign.equals(signs)) {
            throw new ZekeException(400, "错误认证信息");
        }
        QueryWrapper<PresHstDetail> qw = new QueryWrapper<>();
        qw.lambda().eq(PresHstDetail::getOrderNo, hstReq.getOrder_no());
        PresHstDetail hstDetail = presHstDetailService.getOne(qw);
        if (hstDetail == null) {
            logErrorService.presBackLog("处方订单号不存在", "和顺堂回调处方状态异常", "orderNo=" + hstReq.getOrder_no());
            throw new ZekeException(ZkExceptionEnum.PARAMETER_ERROR, "处方订单号不存在");
        }
        PresPrescription presPrescription = presPrescriptionService.getById(hstDetail.getTencode());
        if (presPrescription == null) {
            logErrorService.presBackLog("处方编号号不存在", "和顺堂回调处方状态异常", "tencode=" + hstDetail.getTencode());
            throw new ZekeException(ZkExceptionEnum.PARAMETER_ERROR, "处方编号号不存在");
        }
        HstResDTO<HstExpressResDTO> responseVo = new HstResDTO<>();
        responseVo.setReturn_success("SUCCESS");
        responseVo.setResult_code("200");
        responseVo.setResult_msg(null);
        responseVo.setReturn_msg("SUCCESS");
        HstExpressResDTO resDTO = new HstExpressResDTO();
        resDTO.setIs_success("true");
        responseVo.setResult_data(resDTO);
        if (hstReq.getExpress_num().equals(presPrescription.getExpressno())) {
            //重复请求
            return responseVo;
        }
        presPrescription.setExpressno(hstReq.getExpress_num());
        presPrescription.setExpresscompany(hstReq.getExpress_com_name());
        presPrescription.setUpdateDate(LocalDateTime.now());
        boolean flag = presPrescriptionService.updateById(presPrescription);
        if (!flag) {
            logErrorService.presBackLog("修改处方信息失败", "和顺堂回调处方信息异常", "tencode=" + hstDetail.getTencode());
        }
        return responseVo;
    }

    @Override
    public void updatePresPatientAddrInfo(PresPatientAddrReq req) {
        UpdateWrapper<PresHstDetail> uw = new UpdateWrapper<>();
        uw.lambda().eq(PresHstDetail::getTencode, req.getTencode());
        uw.lambda().set(PresHstDetail::getRecvName, req.getReceiver());
        uw.lambda().set(PresHstDetail::getRecvTel, req.getMobileNumber());
        uw.lambda().set(PresHstDetail::getProvinceName, req.getProvince());
        uw.lambda().set(PresHstDetail::getCityName, req.getCity());
        uw.lambda().set(PresHstDetail::getAreaName, req.getDistrict());
        uw.lambda().set(PresHstDetail::getAddress, req.getAddr());
        boolean flag = presHstDetailService.update(uw);
        if (!flag) {
            throw new ZekeException(400, "修改处方收货人信息失败");
        }
    }

    /**
     * 处理和顺堂处方状态流转
     */
    public void presStatusRoamHst() {
        List<String> thirdIds = presHstDetailService.queryPresStatusRoamThirdPartyIdListHst();
        if (CollectionUtil.isEmpty(thirdIds)) {
            log.info("~~处理和顺堂状态流转,暂无药房订单号处理~~");
//            logErrorService.presBackLog("暂无药房订单号处理", "处理和顺堂制药状态流转", "pharFlag=" + PharConstants.Flag.HR);
            return;
        }
        QueryWrapper<Pharmacy> qp = new QueryWrapper<>();
        qp.lambda().eq(Pharmacy::getFlag, PharConstants.Flag.HST);
        Pharmacy pharmacy = pharmacyService.getOne(qp);
        if (pharmacy == null) {
            logErrorService.presBackLog("药房不存在", "处理和顺堂状态流转", "pharFlag=" + PharConstants.Flag.HST);
            return;
        }
        QueryWrapper<PharmacyDocking> qd = new QueryWrapper<>();
        qd.lambda().eq(PharmacyDocking::getPharId, pharmacy.getId()).eq(PharmacyDocking::getStatus, PharConstants.DockingStatus.NOMER);
        PharmacyDocking pharmacyDocking = pharmacyDockingService.getOne(qd);
        if (pharmacyDocking == null) {
            logErrorService.presBackLog("药房接口信息不存在", "处理和顺堂状态流转", "pharId=" + pharmacy.getId());
            return;
        }
        List<PresPrescription> updateListById = new ArrayList<>(thirdIds.size());
        List<PresHstPharRoam> saveList = new ArrayList<>(thirdIds.size());
        for (String item : thirdIds) {
            if (StringUtils.isBlank(item)) {
                continue;
            }
            String[] splits = item.split(",");
            int status;
            String tcmOrderNo;
            String tencode;
            try {
                status = Integer.parseInt(splits[2]);
                tencode = splits[1];
                tcmOrderNo = splits[0];
                log.info("处方状态,{},药房订单号:{}", status, tcmOrderNo);
            } catch (NumberFormatException e) {
                logErrorService.presBackLog("String转Integer错误", "处理和顺堂状态流转", "res=" + Arrays.toString(splits));
                continue;
            }
            if (StringUtils.isBlank(tcmOrderNo)) {
                logErrorService.presBackLog("订单编号为空", "处理和顺堂状态流转", "res=" + Arrays.toString(splits));
                continue;
            }
            HstCancelPresDTO cancelPresDTO = new HstCancelPresDTO();
            cancelPresDTO.setChannel_id(pharmacyDocking.getMchId());
            cancelPresDTO.setOrder_no(tcmOrderNo);
            Map pramMap = JSONObject.parseObject(JSONObject.toJSONString(cancelPresDTO), Feature.OrderedField);
            String serial = JSON.toJSONString(pramMap);
            String sign = Md5Utils.encryptionMD5(serial + pharmacyDocking.getSecretKey());
            String res = null;
            try {
                HttpHeaders head = new HttpHeaders();
                head.add("Auth-Type", "MD5");
                head.add("Sign", sign.toUpperCase());
                HttpEntity<String> entity = new HttpEntity<>(JsonUtils.objectToStr(cancelPresDTO), head);
                log.info("和顺堂药房查询处方请求参数:{}", JSON.toJSONString(entity));
                res = restTemplate.postForObject(pharmacyDocking.getPreStatusUrl(), entity, String.class);
                log.info("和顺堂药房查询处方返回:{}", res);
            } catch (Exception e) {
                e.printStackTrace();
                logErrorService.presBackLog("药房查询处方状态流转接口异常", "处理和顺堂状态流转", "res=" + res);
            }
            HstResDTO<HstPresDetailResDTO> resDTO = JsonUtils.nativeRead(res, new TypeReference<HstResDTO<HstPresDetailResDTO>>() {
            });
            if (resDTO == null) {
                logErrorService.presBackLog("药房查询处方状态流转接无数据返回", "处理和顺堂状态流转", "res=" + res);
                continue;
            }
            if (!"SUCCESS".equals(resDTO.getReturn_msg()) || !"200".equals(resDTO.getResult_code())) {
                logErrorService.presBackLog("药房查询处方状态流转接返回异常信息", "处理和顺堂状态流转", "res=" + res);
                continue;
            }
            PresPrescription update = new PresPrescription();
            String reason = "";
            HstPresDetailResDTO.Process process = resDTO.getResult_data().getDetails().get(0).getProcess_list().get(0);
            switch (process.getRecord_code()) {
                case "approve_failed":
                    //处方审核不通过
                    if (status != PresConstants.PresStatus.AUDITNO) {
                        update.setStatus(PresConstants.PresStatus.AUDITNO);
                        log.info("审核失败原因:{},处方号:{}", reason, tencode);
                    }
                    break;
                case "approve_complete":
                    //处方审核通过
                    if (status != PresConstants.PresStatus.AUDIT) {
                        update.setStatus(PresConstants.PresStatus.AUDIT);
                    }
                    break;
                case "dispense_medicines_pending":
                case "dispense_medicines_complete":
                    //配药几个状态
                    if (status != PresConstants.PresStatus.ADJUST) {
                        update.setStatus(PresConstants.PresStatus.ADJUST);
                    }
                    break;
                case "check_pending":
                case "check_complete":
                    //复核几个状态
                    if (status != PresConstants.PresStatus.REVIEW) {
                        update.setStatus(PresConstants.PresStatus.REVIEW);
                    }
                    break;
                case "start_medicine_bath_pending":
                case "start_medicine_bath_complete":
                case "medicine_bath_pending":
                case "medicine_bath_complete":
                    //泡药几个状态
                    if (status != PresConstants.PresStatus.BMED) {
                        update.setStatus(PresConstants.PresStatus.BMED);
                    }
                    break;
                case "deliver_decocting_room_pending":
                case "deliver_decocting_room_complete":
                case "start_decocting_medicines_pending":
                case "start_decocting_medicines_complete":
                case "decocting_medicines_pending":
                case "decocting_medicines_complete":
                    //煎药几个状态
                    if (status != PresConstants.PresStatus.TISANES) {
                        update.setStatus(PresConstants.PresStatus.TISANES);
                    }
                    break;
                case "pack_pending":
                case "pack_complete":
                case "logistics_delivery_pending":
                    //打包几个状态
                    if (status != PresConstants.PresStatus.PACK) {
                        update.setStatus(PresConstants.PresStatus.PACK);
                    }
                    break;
                case "logistics_delivery_complete":
                    //发货
                    if (status != PresConstants.PresStatus.DELIVERY) {
                        update.setStatus(PresConstants.PresStatus.DELIVERY);
                    }
                    break;
                case "order_complete":
                    //完成订单
                    if (status != PresConstants.PresStatus.SUC) {
                        update.setStatus(PresConstants.PresStatus.SUC);
                    }
                    break;
                case "logistics_delivery_failed":
                case "pack_failed":
                case "decocting_medicines_failed":
                case "start_decocting_medicines_failed":
                case "deliver_decocting_room_failed":
                case "medicine_bath_failed":
                case "start_medicine_bath_failed":
                case "check_failed":
                case "dispense_medicines_failed":
                    //各种流转异常状态
                    if (status != PresConstants.PresStatus.ERROR) {
                        update.setStatus(PresConstants.PresStatus.ERROR);
                    }
                    log.error("和顺堂处方流转异常,处方单:{},异常类型:{}", tencode, process.getRecord_code());
                    break;
                case "order_cancel":
                    //取消订单
                    if (status != PresConstants.PresStatus.CANCEL) {
                        update.setStatus(PresConstants.PresStatus.CANCEL);
                    }
                    break;
                default:
                    //其他是还未进入审核状态
                    if (status != PresConstants.PresStatus.SENDPHARM) {
                        update.setStatus(PresConstants.PresStatus.SENDPHARM);
                    }
            }
            if (update.getStatus() != null) {
                update.setTencode(tencode);
                update.setUpdateDate(LocalDateTime.now());
                updateListById.add(update);
                PresHstPharRoam record = new PresHstPharRoam();
                record.setTencode(tencode);
                record.setRecordCode(process.getRecord_code());
                record.setRecordCodeName(process.getRecord_code_name());
                record.setCreateDate(LocalDateTime.now());
                record.setOrderNo(tcmOrderNo);
                saveList.add(record);
            }
        }
        if (CollectionUtil.isNotEmpty(updateListById)) {
            presPrescriptionService.updateBatchById(updateListById);
        }
        if (CollectionUtil.isNotEmpty(saveList)) {
            presHstPharRoamService.saveBatch(saveList);
        }
    }

    /**
     * 获取和顺堂药材数据
     */
    public void pullHstDrug() {
        QueryWrapper<Pharmacy> qp = new QueryWrapper<>();
        qp.lambda().eq(Pharmacy::getFlag, PharConstants.Flag.HST);
        Pharmacy pharmacy = pharmacyService.getOne(qp);
        if (pharmacy == null) {
            logErrorService.presBackLog("药房不存在", "获取和顺堂药房药材数据", "pharFlag=" + PharConstants.Flag.HST);
            return;
        }
        QueryWrapper<PharmacyDocking> qd = new QueryWrapper<>();
        qd.lambda().eq(PharmacyDocking::getPharId, pharmacy.getId()).eq(PharmacyDocking::getStatus, PharConstants.DockingStatus.NOMER);
        PharmacyDocking pharmacyDocking = pharmacyDockingService.getOne(qd);
        if (pharmacyDocking == null) {
            logErrorService.presBackLog("药房接口信息不存在", "获取和顺堂药材数据", "pharId=" + pharmacy.getId());
            return;
        }
        Map<String, String> clMap = new HashMap<>();
        clMap.put("channel_id", pharmacyDocking.getMchId());
        Map pramMap = JSONObject.parseObject(JSONObject.toJSONString(clMap), Feature.OrderedField);
        String serial = JSON.toJSONString(pramMap);
        String sign = Md5Utils.encryptionMD5(serial + pharmacyDocking.getSecretKey());
        String res = null;
        try {
            HttpHeaders head = new HttpHeaders();
            head.add("Auth-Type", "MD5");
            head.add("Sign", sign.toUpperCase());
            HttpEntity<String> entity = new HttpEntity<>(JsonUtils.objectToStr(clMap), head);
            log.info("和顺堂药房获取药品目录请求参数:{}", JSON.toJSONString(entity));
            res = restTemplate.postForObject(pharmacyDocking.getGetKlDrugUrl(), entity, String.class);
            log.info("和顺堂药房返回:{}", res);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("和顺堂获取药品目录接口失败:{}", res);
        }
        HstResDTO<HstDrugsResDTO> resDTO = null;
        try {
            resDTO = JsonUtils.nativeRead(res, new TypeReference<HstResDTO<HstDrugsResDTO>>() {
            });
        } catch (Exception e) {
            e.printStackTrace();
            log.info("和顺堂获取药品目录返回数据处理失败:{}", res);
        }
        if (!"SUCCESS".equals(resDTO.getReturn_msg()) || !"200".equals(resDTO.getResult_code())) {
            throw new ZekeException("和顺堂药房获取药品目录接口失败,原因:{}", resDTO.getResult_msg());
        }
        log.info("=====进入药材获取====");
        drugsModelService.syncHstDrugInfo(resDTO.getResult_data().getList(), pharmacy.getId());
    }

    /**
     * 设置物流回调地址
     */
    public void setExpressUrl() {
        QueryWrapper<Pharmacy> qp = new QueryWrapper<>();
        qp.lambda().eq(Pharmacy::getFlag, PharConstants.Flag.HST);
        Pharmacy pharmacy = pharmacyService.getOne(qp);
        if (pharmacy == null) {
            logErrorService.presBackLog("药房不存在", "设置和顺堂药房处方物流回调url", "pharFlag=" + PharConstants.Flag.HST);
            return;
        }
        QueryWrapper<PharmacyDocking> qd = new QueryWrapper<>();
        qd.lambda().eq(PharmacyDocking::getPharId, pharmacy.getId()).eq(PharmacyDocking::getStatus, PharConstants.DockingStatus.NOMER);
        PharmacyDocking pharmacyDocking = pharmacyDockingService.getOne(qd);
        if (pharmacyDocking == null) {
            logErrorService.presBackLog("药房接口信息不存在", "设置和顺堂药房处方物流回调url", "pharId=" + pharmacy.getId());
            return;
        }
        Map<String, String> clMap = new HashMap<>();
        clMap.put("channel_id", pharmacyDocking.getMchId());
        clMap.put("notice_url", pharmacyDocking.getPresCallbackUrl());
        String serial = JSON.toJSONString(clMap, SerializerFeature.MapSortField);
        String sign = Md5Utils.encryptionMD5(serial + pharmacyDocking.getSecretKey());
        String res = null;
        try {
            HttpHeaders head = new HttpHeaders();
            head.add("Auth-Type", "MD5");
            head.add("Sign", sign.toUpperCase());
            HttpEntity<String> entity = new HttpEntity<>(JsonUtils.objectToStr(clMap), head);
            log.info("设置和顺堂药房处方物流回调url请求参数:{}", JSON.toJSONString(entity));
            res = restTemplate.postForObject(pharmacyDocking.getSetExpressUrl(), entity, String.class);
            log.info("和顺堂药房返回:{}", res);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("设置和顺堂药房处方物流回调url失败:{}", res);
        }
        try {
            HstResDTO<HstSetExpressResDTO> resDTO = JsonUtils.nativeRead(res, new TypeReference<HstResDTO<HstSetExpressResDTO>>() {
            });
            log.info("设置和顺堂药房处方物流回调url响应信息:{}", resDTO);
            if (!resDTO.getResult_code().equals("200")) {
                throw new ZekeException(400, "设置物流回调失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("设置和顺堂药房处方物流回调url处理失败:{}", res);
        }
    }
}
